//package com.huawei.java.main.optimization;
//
//import com.huawei.java.main.client.ClientDemand;
//import com.huawei.java.main.io.Writer;
//import com.huawei.java.main.schedule.BandSchedule;
//import com.huawei.java.main.server.ServerBandwidth;
//import com.huawei.java.main.server.ServerClientQos;
//
//import java.io.IOException;
//import java.util.*;
//
///**
// * @author dengguoli
// * @date 2022/3/18
// * @since jdk1.8
// */
//public class OptimizationCost {
//
//    // server band
//    private ServerBandwidth bandwidth;
//
//    // client demand
//    private BandSchedule bandSchedule;
//
//    // qos
//    private ServerClientQos clientQos;
//
//    // clientDemand
//    private ClientDemand clientDemand;
//
//    // 最终结果,传给bandSchedule
//    private List<Scheduler> finalSolution;
//
//    // server分配的baseline
//    private Map<String, Integer> serverBaseline;
//
//    // 一个client对应多少个server
//    private Map<String, Set<String>> clientServerQosList;
//    // 一个server对于多少个client
//    private Map<String, Set<String>> serverClientQosList;
//
//    // 全局可提供流量能力
//    Map<String, Integer> serverBandAbilityMap;
//
//
//    //
//
//
//    // 为最大需求设定标准线
//    public List<Map<String, Integer>> setBaseline() {
//        //全部server的band
//        Map<String, Integer> serverBandAbilityMap = new HashMap<>(this.bandwidth.getServerBandMap());
//
//        String[] clientName = this.clientDemand.getClientName();
//        Integer[] maxClientDemand = this.clientDemand.getMaxClientDemand();
//
//        //每个客户端和他们对应server的分配
//        List<Map<String, Integer>> clientServersSolution = new ArrayList<>(clientName.length);
//
//        for (int i = 0; i < maxClientDemand.length-1; i++) {
//            // 判断单台服务器承受能力，标记不能承受全部流量服务器
//            // 每个客户端调度的结果存储,string-servernaem，integer-调度数量
//            Map<String, Integer> eachClientSolution = new HashMap<>();
//            int scheduleSuccess = isScheduled(serverBandAbilityMap, maxClientDemand[i], clientName[i], eachClientSolution);
//            clientServersSolution.add(eachClientSolution);
//            // 如果分配流量超载，取出之前已分配数据，二次分配
//            if (scheduleSuccess > 0) {
//                int doubleScheduleSuccess = scheduleSuccess;
//                for (int j = i-1; j >= 0; j --) {
//                    doubleScheduleSuccess = isScheduled(serverBandAbilityMap, doubleScheduleSuccess, clientName[j], clientServersSolution.get(j));
//                    if (doubleScheduleSuccess == 0) {
//                        // 更新当前client位置
//                        i = j + 1;
//                        break;
//                    }
//                }
//            }
//            // 二次分配结束
//            // 单台服务器承受能力
//        }
//        for (int i = 0; i < clientServersSolution.size(); i++) {
//            System.out.println(clientServersSolution.get(i));
//        }
//        return clientServersSolution;
//    }
//
//    // 判断此次是否分配成功,成功则无需二次分配，失败进入二次分配，结果写入clientServersSolution
//    private Integer isScheduled(Map<String, Integer> serverBandAbilityMap, Integer demand, String clientName, Map<String, Integer> singleClientSolution) {
//        if (demand == 0) {
//            return 0;
//        }
//        Map<String, Set<String>> clientServerQosList = this.clientServerQosList;
//        List<String> serversList = new ArrayList<>(clientServerQosList.get(clientName));
//        // 每个服务器所占比例
//        Map<String, Double> serverProportion = new HashMap<>(serversList.size());
//        // 根据每个client能够获得的band总量，其中各个server的剩余占比能力来确定将demand分配到具体server的比例
//        // 第一步计算占比:
//        Integer total = 0;
//        // 每个client对应的server
//        for (String server : serversList) {
//            Integer integer = serverBandAbilityMap.get(server);
//            total += integer;
//        }
//        // 可用流量小等于需求
//        if(total < demand) {
//            return demand - total;
//        }
//        else if ((total - demand) < total*0.1) {
//            // 设置调度结果
//            int i = 0;
//            while (demand > 0) {
//                String serverName = serversList.get(i);
//                demand -= serverBandAbilityMap.get(serverName);
//                serverBandAbilityMap.put(serverName, 0);
//                int temp = serverBandAbilityMap.get(serverName);
//                singleClientSolution.compute(serverName, (k, v)-> v + temp);
//                i ++;
//            }
//            return 0;
//        }
//        else {
//            // 总可用流量大于总需求流量
//            // 计算分配比例
//            // 剩余band值
//            int band = demand;
//            for (int i = 0; i < serversList.size(); i++) {
//                // 最后一次更新
//                if (i == serversList.size()-1) {
//                    // 设置单次的结果
//                    singleClientSolution.put(serversList.get(i), band);
//                    // 更新全部serverBandAbilityMap
//                    int finalBand = band;
//                    serverBandAbilityMap.compute(serversList.get(i), (k, v) -> v- finalBand);
//                    break;
//                }
//                Double proportion = serverBandAbilityMap.get(serversList.get(i)) / (double)total;
//                int value = (int) (proportion * demand);
//                // 设置单次的结果
//                singleClientSolution.put(serversList.get(i), value);
//                // 更新全部serverBandAbilityMap
//                serverBandAbilityMap.compute(serversList.get(i), (k, v) -> v-value);
//                // 更新band
//                band -= value;
//            }
//            //分配成功，返回0
//            return 0;
//        }
//    }
//
//    // 为每行分配，无负载算法
//    public List<Map<String, Integer>> setNormalLines(Integer[] maxClientDemand) {
//        //全部server的band
//        Map<String, Integer> serverBandAbilityMap = this.serverBandAbilityMap;
//
//        String[] clientName = this.clientDemand.getClientName();
//
//        //每个客户端和他们对应server的分配
//        List<Map<String, Integer>> clientServersSolution = new ArrayList<>(clientName.length);
//
//        for (int i = 0; i < maxClientDemand.length; i++) {
//            // 判断单台服务器承受能力，标记不能承受全部流量服务器
//            // 每个客户端调度的结果存储,string-servernaem，integer-调度数量
//            Map<String, Integer> eachClientSolution = new HashMap<>();
//            int scheduleSuccess = isScheduled(serverBandAbilityMap, maxClientDemand[i], clientName[i], eachClientSolution);
//            clientServersSolution.add(eachClientSolution);
//            // 如果分配流量超载，取出之前已分配数据，二次分配
//            if (scheduleSuccess > 0) {
//                int doubleScheduleSuccess = scheduleSuccess;
//                for (int j = i-1; j >= 0; j --) {
//                    doubleScheduleSuccess = isDoubleScheduled(serverBandAbilityMap, doubleScheduleSuccess, clientName[j], clientName[j+1], clientServersSolution.get(j));
////                    doubleScheduleSuccess = isScheduled(serverBandAbilityMap, doubleScheduleSuccess, clientName[j], clientServersSolution.get(j));
//                    if (doubleScheduleSuccess == 0) {
//                        // 更新当前client位置
//                        i = j + 1;
//                        break;
//                    }
//                }
//            }
//            // 二次分配结束
//            // 单台服务器承受能力
//        }
////        for (Map<String, Integer> stringIntegerMap : clientServersSolution) {
////            System.out.println(stringIntegerMap);
////        }
//        return clientServersSolution;
//    }
//
//    private Integer isDoubleScheduled(Map<String, Integer> serverBandAbilityMap, int demand, String clientNow, String clientNext, Map<String, Integer> clientScheduleNow) {
//        if (demand == 0) {
//            return 0;
//        }
//        // 取得与下一个分配相关的server，查看当前client上减去公共server，还能存放多少
//        Set<String> clientsNow = this.clientServerQosList.get(clientNow);
//        Set<String> clientsNext = this.clientServerQosList.get(clientNext);
//        ArrayList<String> similarityServers = new ArrayList<>();
//
//        for (String now : clientsNow) {
//            if (!clientsNext.contains(now)) {
//                similarityServers.add(now);
//            }
//        }
//
//        // 计算总共还可以分配流量
//        Integer sumBand = 0;
//        for (String similarityServer : similarityServers) {
//            Integer tempBand = serverBandAbilityMap.get(similarityServer);
//            sumBand += tempBand;
//        }
//
//        if (sumBand < demand) {
//        // 分配不成功，返回缺少流量数
//            return demand - sumBand;
//        }
//        else if ((sumBand - demand) < sumBand*0.1) {
//            // 设置调度结果
//            int i = 0;
//            while (demand > 0) {
//                String serverName = similarityServers.get(i);
//                demand -= serverBandAbilityMap.get(serverName);
//                serverBandAbilityMap.put(serverName, 0);
//                int temp = serverBandAbilityMap.get(serverName);
//                clientScheduleNow.compute(serverName, (k, v)-> v + temp);
//                i ++;
//            }
//            return 0;
//        }
//        else {
//            // 总可用流量大于总需求流量
//            // 计算分配比例
//            // 剩余band值
//            int band = demand;
//            for (int i = 0; i < similarityServers.size(); i++) {
//                // 最后一次更新
//                if (i == similarityServers.size()-1) {
//                    int finalBand = band;
//                    // 增加单次的结果
//                    clientScheduleNow.compute(similarityServers.get(i), (k, v) -> v + finalBand);
//                    // 更新全部serverBandAbilityMap
//                    serverBandAbilityMap.compute(similarityServers.get(i), (k, v) -> v- finalBand);
//                    break;
//                }
//                double proportion = serverBandAbilityMap.get(similarityServers.get(i)) / (double)sumBand;
//                int value = (int) (proportion * demand);
//                // 设置单次的结果
//                clientScheduleNow.compute(similarityServers.get(i), (k, v) -> v + value);
//                // 更新全部serverBandAbilityMap
//                serverBandAbilityMap.compute(similarityServers.get(i), (k, v) -> v-value);
//                // 更新band
//                band -= value;
//            }
//            //分配成功，返回0
//            return 0;
//        }
//
//    }
//
//    public List<Scheduler> getFinalSolution() {
//        return finalSolution;
//    }
//
//    public void setFinalSolution(List<Scheduler> finalSolution) {
//        this.finalSolution = finalSolution;
//    }
//
//    public Map<String, Integer> getServerBaseline() {
//        return serverBaseline;
//    }
//
//    public void setServerBaseline(Map<String, Integer> serverBaseline) {
//        this.serverBaseline = serverBaseline;
//    }
//
//    public Map<String, Set<String>> getClientServerQosList() {
//        return clientServerQosList;
//    }
//
//    public void setClientServerQosList(Map<String, Set<String>> clientServerQosList) {
//        this.clientServerQosList = clientServerQosList;
//    }
//
//    public Map<String, Set<String>> getServerClientQosList() {
//        return serverClientQosList;
//    }
//
//    public void setServerClientQosList(Map<String, Set<String>> serverClientQosList) {
//        this.serverClientQosList = serverClientQosList;
//    }
//
//    //存放结果
//    public OptimizationCost(ServerBandwidth bandwidth, BandSchedule bandSchedule, ServerClientQos clientQos, ClientDemand clientDemand) {
//        this.bandwidth = bandwidth;
//        this.bandSchedule = bandSchedule;
//        this.clientQos = clientQos;
//        this.clientDemand = clientDemand;
//        this.clientServerQosList = clientDemand.getServerClientQos().getClientServerQosList();
//        this.serverClientQosList = clientDemand.getServerClientQos().getServerClientQosList();
//        this.serverBandAbilityMap = this.bandwidth.getServerBandMap();
//    }
//
//    public void sum() {
//        ClientDemand clientDemand = this.clientDemand;
//        ClientDemand.EachDemand[] allClientDemand = clientDemand.getAllClientDemand();
//        String[] clientName = clientDemand.getClientName();
//        List<String> solutionOutput = new ArrayList<>(clientDemand.getAllClientDemand().length);
//
//        for (ClientDemand.EachDemand eachDemand : allClientDemand) {
//
//            List<Map<String, Integer>> maps = setNormalLines(eachDemand.getEachClientDemand());
//
//
//            for (int j = 0; j < clientName.length; j++) {
//                StringBuilder solution = new StringBuilder();
//                solution.append(clientName[j]);
//                solution.append(":");
//                if (maps.get(j).size() == 0) {
//                    solution.append(":");
//                }
//
//                maps.get(j).forEach((k, v) -> {
//                    if (v > 0) {
//                        solution.append("<");
//                        solution.append(k);
//                        solution.append(",");
//                        solution.append(v);
//                        solution.append(">");
//                        solution.append(",");
//                    }
//                });
//                solution.deleteCharAt(solution.length() - 1);
//                solution.append("\n");
//                solutionOutput.add(solution.toString());
//            }
//        }
//        Writer.writeTxt(solutionOutput);
//    }
//
//
//    public ServerBandwidth getBandwidth() {
//        return bandwidth;
//    }
//
//    public void setBandwidth(ServerBandwidth bandwidth) {
//        this.bandwidth = bandwidth;
//    }
//
//    public BandSchedule getBandSchedule() {
//        return bandSchedule;
//    }
//
//    public void setBandSchedule(BandSchedule bandSchedule) {
//        this.bandSchedule = bandSchedule;
//    }
//
//    public ServerClientQos getClientQos() {
//        return clientQos;
//    }
//
//    public void setClientQos(ServerClientQos clientQos) {
//        this.clientQos = clientQos;
//    }
//
//    public ClientDemand getClientDemand() { return clientDemand; }
//
//    public void setClientDemand(ClientDemand clientDemand) { this.clientDemand = clientDemand; }
//
//}
